package com.hu.uitl;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class ThreadDown{
    //线程数量
    public static int threadCount = 3;
    //记录线程下载文件标识，所有线程下载完成则文件下载完成
    public static int runningThread = threadCount;

    public static void main(String[] args) throws MalformedURLException {
        //1.获取文件大小，创建一个和服务器文件对应的临时文件
        //2.计算分配几个线程下载服务器资源，知道每个线程下载文件的位置
        //3.开启多线程  开始位置：（线程id-1）* 每一块大小   结束位置：（线程id* 每一块大小）-1
        String path = "http://img.netbian.com/file/2017/0713/bb096e7fc133ddfbe1d409cf9340800b.jpg";
        URL url = new URL(path);
        try {
            String newFileName = path.substring(path.lastIndexOf("/") + 1);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5000);
            conn.setRequestMethod("GET");
            int code = conn.getResponseCode();
            if(code == 200){
                //服务器文件总大小
                int length = conn.getContentLength();
                int blockSize = length / threadCount; //每一块的大小
                //在客户端本地创建一个跟服务端大小一致的临时文件
                RandomAccessFile raf = new RandomAccessFile(newFileName,"rwd");
                raf.setLength(length);
                raf.close();

                for(int threadId=1;threadId <= threadCount ; threadId ++){
                    int startIndex = (threadId - 1) * blockSize;
                    int endIndex = (threadId * blockSize) - 1;
                    if(threadId == threadCount){ //如果线程是最后一个，则结束位置为最后位置
                        endIndex = length ;
                    }
                    //下载文件
                    new DownloadFileThread(path, startIndex, endIndex, threadId){}.start();
                }

            }else{
                System.out.println("请求失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static class DownloadFileThread extends Thread {
        private String filepath;
        private int startIndex;
        private int endIndex;
        private int threadId;
        private String newFileName;

        public DownloadFileThread(String filepath, int startIndex, int endIndex,int threadId) {
            this.filepath = filepath;
            this.startIndex = startIndex;
            this.endIndex = endIndex;
            this.threadId = threadId;
            this.newFileName = filepath.substring(filepath.lastIndexOf("/") + 1);
        }

        @Override
        public void run() {
            try {
                //为支持断点续传，终止或异常发生时，保存文件下载的最后位置，下次继续下载时读取出来，从上次结束位置开始下载
                //判断是否存在已下载的文件记录，如果存在则开始位置
                File file = new File(threadId + ".txt");
                if(file.exists() && file.length() > 0){
                    String tempFileContent = txt2String(file);
                    startIndex = Integer.parseInt(tempFileContent);
                }

                URL url = new URL(filepath);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestProperty("User-Agent", "NetFox"); // 设置User-Agent
                conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);//请求资源的范围，下载部分文件，需指定开始-结束位置
                conn.setConnectTimeout(5000);
                conn.setRequestMethod("GET");
                int code = conn.getResponseCode();//200是成功，206也是成功，分割一个文件返回206
                InputStream is = conn.getInputStream(); //由于设置了请求的位置，返回的是当前位置对应的输入流

                RandomAccessFile raf = new RandomAccessFile(newFileName,"rwd");
                raf.seek(startIndex);
                int len = 0 , total = 0;
                byte[] buffer = new byte[1024];
                while((len = is.read(buffer)) != -1){//没有读到文件末尾则继续写
                    raf.write(buffer, 0, len);
                    total += len;
                    RandomAccessFile info = new RandomAccessFile(threadId + ".txt","rwd");
                    info.write((total + startIndex + "").getBytes());//把下载到最后的位置保存写到文件中
                    info.close();
                }
                is.close();
                raf.close();
                //System.out.println("线程:"+threadId +"------下载完毕");
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally{
                runningThread --;
                //当线程执行完后，表示文件下载完毕，清除临时文件记录
                if(runningThread == 0){
                    for(int i=1;i <= threadCount; i++){
                        File file = new File(i+".txt");
                        if(file.exists()){
                            file.delete();
                        }
                    }
                }
            }
        }

        /**
         * 读取txt文件的内容
         * @param file 想要读取的文件对象
         * @return 返回文件内容
         */
        public static String txt2String(File file){
            StringBuilder result = new StringBuilder();
            try{
                BufferedReader br = new BufferedReader(new FileReader(file));//构造一个BufferedReader类来读取文件
                String s = null;
                while((s = br.readLine())!=null){//使用readLine方法，一次读一行
                    result.append(s);
                }
                br.close();
            }catch(Exception e){
                e.printStackTrace();
            }
            return result.toString();
        }

    }

}





